package sample.jogl;
import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;

/** This JPanel subclass animates the dropping of a ball.**/
public class Drop2DPanel extends JPanel{

  // Parameters for the drop
  double fY = 0.0, fVy = 0.0;
  // Conversion factor from cm to pixels.
  double fYConvert = 0.0;
  double fXPixel = 0.0, fYPixel = 0.0;
  double fRadius = 0.0, fDiam = 0.0;
  // starting point for ball in cm
  double fY0 = 1000.0;
  // Frame dimensions.
  double fFrameHt, fFrameWd;
    // Flag for drop status
  boolean fDropDone = false;

  Ellipse2D fBall;

  /** Reset parameters for a new drop. **/
  void reset(){
    fFrameHt = getHeight();
    fFrameWd = getWidth();

    fXPixel = getWidth()/2;
    fY = fY0; fVy = 0;

    // Conversion factor from cm to pixels
    // Start the ball about 20% from the top
    // of the frame
    fYConvert = fFrameHt / (1.2 * fY0);

    // Choose a size for the ball relative to the
    // height in pixel units.
    fRadius = (int)((0.1 * fY0) * fYConvert);
    fDiam = 2 * fRadius;

    fBall = new Ellipse2D.Double(fXPixel-fRadius,
                                 fYPixel-fRadius,
                                 fDiam,fDiam);
    setBackground(Color.WHITE);
    fDropDone=false;
  } // reset

  /** Draw the ball at its current position. **/
  public void paintComponent (Graphics g){
    super.paintComponent(g);
    Graphics2D g2 = (Graphics2D)g;
    // Antialiasing for smooth surfaces.
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
          RenderingHints.VALUE_ANTIALIAS_ON);

    // Determine position after this time increement
    calcPosition ();
    // Move the ball.
    fBall.setFrame(fXPixel-fRadius,
                   fYPixel-fRadius,
                   fDiam,fDiam);
    // Want a solid red ball
    g2.setColor (Color.RED);
    g2.fill(fBall);

    // Now draw the ball.
    g2.draw (fBall);
  } // paintComponent

  /** Calculate the ball position in the next frame. **/
  void calcPosition () {
    // Increment by 10 millseconds per frame
    double dt = 0.025;

    // Calculate position and velocity at each step
    fY = fY + fVy * dt - 490.* dt * dt;
    fVy = fVy  -  980.0 * dt;

    // Convert to the pixel coordinates
    fYPixel = fFrameHt - (int)(fY * fYConvert);

    // Reverse direction when ball hits bottom.
    if ((fYPixel + fRadius) >= (fFrameHt-1)) {
         fVy = Math.abs (fVy);
         // Subtract friction loss
         fVy -= 0.1*fVy;
         // Stop when speed at bottom drops below arbitrary limit
         if (fVy < 15.0) {
             fDropDone=true;
         }
    }
  } // clacPosition

  /** Provide a flag on drop status. **/
  public boolean isDone () {
    return fDropDone;
  }

} // class DropPanel